package com.ruyuan.eshop.diplomacy.manager.common.db;

import com.alibaba.nacos.common.utils.MapUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.ruyuan.eshop.diplomacy.domain.dao.DiplomacyDAO;
import com.ruyuan.eshop.diplomacy.domain.entity.SkuSellerRelationDO;
import com.ruyuan.eshop.common.enums.DelFlagEnum;
import com.ruyuan.eshop.diplomacy.manager.common.cache.RedisSortedSetCache;
import com.ruyuan.eshop.diplomacy.mapper.SkuSellerRelationMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;

import static com.ruyuan.eshop.common.constants.diplomacy.BaseConstants.LONG_FIVE_MINUTES;
import static com.ruyuan.eshop.common.constants.diplomacy.BaseConstants.PAGE_SIZE_100;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;

/**
 * redis(sorted set)数据源抽象类
 *
 * @author zhonghuashishan
 */
@Slf4j
public abstract class AbstractRedisSortedSetDatabase implements RedisSortedSetDatabase {
    
    @Resource
    private DiplomacyDAO diplomacyDAO;

    @Resource
    private SkuSellerRelationMapper skuSellerRelationMapper;

    /**
     * 5分钟内单表变更数据主键ID集合
     * 
     * @param tableName 
     * @return java.util.Optional<java.util.Set<java.lang.String>>
     * @author zhonghuashishan
     */
    private Optional<Set<String>> getSingleTableUpdateIdSet(String tableName) {
        // 获取最近5分钟时间
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String beforeDate = simpleDateFormat.format(new Date(System.currentTimeMillis() - LONG_FIVE_MINUTES));

        // 获取sql
        String sql = "SELECT ID FROM " + tableName + " WHERE UPDATE_TIME>'" + beforeDate + "'";
        List<Map<String, Object>> mapList = diplomacyDAO.select(sql);
        if (CollectionUtils.isEmpty(mapList)) {
            return Optional.empty();
        }
        Set<String> idSet = mapList.stream().map(fieldMap -> String.valueOf(fieldMap.get("id"))).collect(toSet());
        return Optional.of(idSet);
    }

    /**
     * 获取增量数据
     *
     * @param tableName
     * @return java.util.Optional<java.util.Map<java.lang.String,com.ruyuan.eshop.diplomacy.manager.common.source.RedisSortedSetSource>>
     * @author zhonghuashishan
     */
    @Override
    public Optional<Map<String, RedisSortedSetCache>> listIncrMap(String tableName) {
        Optional<Set<String>> idSetOpt = getSingleTableUpdateIdSet(tableName);
        if (!idSetOpt.isPresent()) {
            return Optional.empty();
        }
        return listIncrMap(tableName, idSetOpt.get());
    }

    @Override
    public Optional<RedisSortedSetCache> listEntityData() {
        QueryWrapper<SkuSellerRelationDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("DEL_FLAG", DelFlagEnum.EFFECTIVE.getCode());
        List<SkuSellerRelationDO> skuSellerRelationDOList = skuSellerRelationMapper.selectList(queryWrapper);
        if (CollectionUtils.isEmpty(skuSellerRelationDOList)) {
            return Optional.empty();
        }
        RedisSortedSetCache redisSortedSetCache = new RedisSortedSetCache();
        redisSortedSetCache.setAddList(skuSellerRelationDOList);
        return Optional.of(redisSortedSetCache);
    }

    /**
     * 获取全部表数据
     *
     * @return java.util.Optional<java.util.Map<java.lang.String,com.ruyuan.eshop.diplomacy.manager.common.source.RedisSortedSetSource>>
     * @author zhonghuashishan
     */
    @Override
    public Optional<Map<String, RedisSortedSetCache>> listAllTableData() {
        Optional<List<String>> allIdListOpt = getTableAllIdList();
        if (!allIdListOpt.isPresent()) {
            return Optional.empty();
        }
        List<List<String>> partitionList = Lists.partition(allIdListOpt.get(), PAGE_SIZE_100);
        Map<String, RedisSortedSetCache> resultMap = Maps.newHashMap();
        for (List<String> list : partitionList) {
            Optional<Map<String, RedisSortedSetCache>> sortedSetSourceOpt = listIncrMap(getTableName(), Sets.newHashSet(list));
            if (!sortedSetSourceOpt.isPresent()) {
                continue;
            }

            for (Map.Entry<String, RedisSortedSetCache> entry : sortedSetSourceOpt.get().entrySet()) {
                String key = entry.getKey();
                Map<String, Double> addMap = entry.getValue().getAddMap();
                Set<String> partDeleteSet = entry.getValue().getDeleteMemberSet();
                if (!resultMap.containsKey(key)) {
                    RedisSortedSetCache redisSortedSetCache = new RedisSortedSetCache();
                    resultMap.put(key, redisSortedSetCache);
                }
                resultMap.get(key).getDeleteMemberSet().addAll(partDeleteSet);
                resultMap.get(key).getAddMap().putAll(addMap);
            }
        }

        return MapUtils.isEmpty(resultMap) ? Optional.empty() : Optional.of(resultMap);
    }

    /**
     * 获取单表所有主键ID集合
     *
     * @param
     * @return java.util.Optional<java.util.List<java.lang.String>>
     * @author zhonghuashishan
     */
    @Override
    public Optional<List<String>> getTableAllIdList() {
        String sql = "SELECT ID FROM " + getTableName();
        List<Map<String, Object>> mapList = diplomacyDAO.select(sql);
        if (CollectionUtils.isEmpty(mapList)) {
            return Optional.empty();
        }
        List<String> idSet = mapList.stream().map(fieldMap -> String.valueOf(fieldMap.get("ID"))).collect(toList());
        return Optional.of(idSet);
    }
}
